﻿using System;
using System.IO;
using System.Data;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using ACSTools.RestConsumer;
using ACSTools.DataContracts;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace ACSTools.Win
{
    public partial class frmBD : Form
    {

        #region Locals

            private PrimeHomeWS phWS;
            
            public frmBD()
            {
                InitializeComponent();
                phWS = new PrimeHomeWS();
                deviceWorker.WorkerReportsProgress = true;
                deviceWorker.WorkerSupportsCancellation = true;
                subscriberWorker.WorkerReportsProgress = true;
                subscriberWorker.WorkerSupportsCancellation = true;
            }
                    
            protected class targetDevice
            {
                public targetDevice(string deviceID, string deviceMAC, string deviceOUI, string subscriberCode, string deviceDisposition, DateTime deviceLastInform) 
                {
                    this.deviceID = deviceID;
                    this.deviceMAC = deviceMAC;
                    this.deviceOUI = deviceOUI;
                    this.subscriberCode = subscriberCode;
                    this.deviceDisposition = deviceDisposition;
                    this.deviceLastInform = deviceLastInform.Date;
                    this.deviceStatus = "Listo para eliminar!";
                }
                
                public string deviceID { get; set; }
                public string deviceMAC { get; set; }
                public string deviceOUI { get; set; }
                public string subscriberCode { get; set; }
                public string deviceDisposition { get; set; }
                public DateTime deviceLastInform { get; set; }
                public string deviceStatus { get; set; }
            }

            protected class targetSubscriber
            {
                public targetSubscriber(string subscriberId , string subscriberCode, string subscriberName, string deviceCount) 
                {
                    this.subscriberId = subscriberId;
                    this.subscriberCode = subscriberCode;
                    this.subscriberName = subscriberName;
                    this.deviceCount = deviceCount;
                    this.subscriberStatus = "Listo para eliminar!";
                }

                public string subscriberId { get; set; }
                public string subscriberCode { get; set; }
                public string subscriberName { get; set; }
                public string deviceCount { get; set; }
                public string subscriberStatus { get; set; }
            }

            protected calqResult[] calqResults;    
        
            protected List<targetDevice> targetDevices;

            protected List<targetSubscriber> targetSubscribers;

            protected BindingSource dbSource = new BindingSource();

            protected DateTime initTime = new DateTime();

            protected DateTime termTime = new DateTime();

        #endregion

        #region Events

        private void frmBD_Load(object sender, EventArgs e)
            {

            }

        private void cmdLoad_Click(object sender, EventArgs e)
        {
            lockGUI();
            try
            {
                if (rbtDevices.Checked)
                {
                    if (rcbFutureDeviceOnly.Checked | rcbOrphanOnly.Checked | rcbLastInform.Checked)
                    {
                        loadDevices();
                    }
                    else throw new Exception("Debe elegir al menos una opcion de filtrado para eliminar dispositivos!");
                }
                else loadSubscribers();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                unlockGUI();
            }
        }

        private void cmdCancel_Click(object sender, EventArgs e)
        {
            // Disable active commands
            cmdCancel.Enabled = false;
            cmdDelete.Enabled = false;

            if (rbtDevices.Checked)
            {
                if (deviceWorker.IsBusy)
                {
                    deviceWorker.CancelAsync();
                }
                else
                {
                    resetDataObjects();
                    resetGUI();
                    unlockGUI();
                }
            }
            else
            {
                if (subscriberWorker.IsBusy)
                {
                    subscriberWorker.CancelAsync();
                }
                else
                {
                    resetDataObjects();
                    resetGUI();
                    unlockGUI();
                }
            }
        }

        private void cmdDelete_Click(object sender, EventArgs e)
        {
            try
            {
                cmdDelete.Enabled = false;
                initTime = DateTime.Now;
                dtgTargets.Enabled = false;
                if (rbtDevices.Checked)
                {
                    deviceWorker.RunWorkerAsync();
                }
                else subscriberWorker.RunWorkerAsync();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                dtgTargets.Enabled = true;
            }
        }

        private void cmdSaveLog_Click(object sender, EventArgs e)
        {
            // Open save file dialog
            string line = "";
            saveFileDialog.ShowDialog();
            string fileName = saveFileDialog.FileName;
            // Execute
            if (fileName != "")
            {
                // Disable save button
                cmdSaveLog.Enabled = false;
                // Write log
                try
                {
                    StreamWriter sw = new StreamWriter(fileName, false);
                    // Write log header
                    sw.WriteLine("************************ Registro de Resultados ************************");
                    sw.WriteLine("Proceso de eliminación de " + ((rbtDevices.Checked) ? "dispositivos" : "subscriptores"));
                    sw.WriteLine("Fecha: " + DateTime.Now.ToShortDateString());
                    sw.WriteLine("Inicio: " + initTime.ToLongTimeString());
                    sw.WriteLine("Finalizado: " + termTime.ToLongTimeString());
                    TimeSpan elapsedTime = (DateTime.Now - initTime);
                    sw.WriteLine("Duracion: " + elapsedTime.Hours.ToString() + " Horas, " + elapsedTime.Minutes.ToString() + " Minutos, " + elapsedTime.Seconds.ToString() + " Segundos");
                    if (rbtDevices.Checked)
                    {
                        // Devices
                        if (targetDevices != null) sw.WriteLine("Registros: " + targetDevices.Count.ToString());
                        sw.WriteLine("************************************************************************");
                        sw.WriteLine("ID,MAC,OUI,Suscriptor,Ultimo Informe (M/D/Y),Estado");
                        foreach (targetDevice target in targetDevices)
                        {
                            line = target.deviceID + "," +
                                   target.deviceMAC + "," +
                                   target.deviceOUI + "," +
                                   ((target.subscriberCode != null) ? (target.subscriberCode + ",") : ",") +
                                   target.deviceLastInform.ToShortDateString() + "," +
                                   target.deviceStatus;
                            sw.WriteLine(line);
                        }
                    }
                    else
                    {
                        // Subscribers
                        if (targetSubscribers != null) sw.WriteLine("Registros: " + targetSubscribers.Count.ToString());
                        sw.WriteLine("************************************************************************");
                        sw.WriteLine("ID,Codigo,Nombre,Dispositivos,Estado");
                        foreach (targetSubscriber target in targetSubscribers)
                        {
                            line = target.subscriberId + "," +
                                   target.subscriberCode + "," +
                                   target.subscriberName + "," +
                                   target.deviceCount + "," +
                                   target.subscriberStatus;
                            sw.WriteLine(line);
                        }
                    }
                    sw.WriteLine("***************************** Ultima Linea *****************************");
                    sw.Close();
                    sw.Dispose();
                }
                catch (Exception ex)
                {
                    cmdSaveLog.Enabled = true;
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                resetDataObjects();
                resetGUI();
                unlockGUI();
            }
        }

        private void dtgTargets_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.C && e.Control)
            {
                string copyStr = ConvertSelectedDataToString(this.dtgTargets);
                Clipboard.SetDataObject(copyStr);
            }
        }

        private void rbtDevices_CheckedChanged(object sender, EventArgs e)
        {
            rcbFutureDeviceOnly.Enabled = rbtDevices.Checked;
            rcbOrphanOnly.Enabled = rbtDevices.Checked;
            rcbLastInform.Enabled = rbtDevices.Checked;
            rdtLastInform.Enabled = rcbLastInform.Checked && rcbLastInform.Enabled;
        }

        private void rcbLastInform_CheckedChanged(object sender, EventArgs e)
        {
            rdtLastInform.Enabled = rcbLastInform.Checked;
        }

        private void subscriberWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            targetSubscriber target;
            int progressPercentage = 0;
            int targetCount = targetSubscribers.Count;
            BackgroundWorker worker = (BackgroundWorker)sender;
            dbSource.MoveFirst();
            for (int i = 0; i <= (targetCount - 1); i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    Thread.Sleep(2000);
                    target = targetSubscribers[i];
                    target.subscriberStatus = "";
                    // Filtro eliminacion subscriptores 
                    string filteredDevices = "";
                    if (filteredDevices.IndexOf(target.subscriberId) == 0)
                    {
                        // Eliminar subscriptor
                        if (deleteSubscriber(target.subscriberId))
                        {
                            target.subscriberStatus = "suscriptor eliminado!";
                        }
                        else
                        {
                            target.subscriberStatus = "suscriptor no eliminado!";
                        }
                    }
                    else
                    {
                        target.subscriberStatus += "suscriptor filtrado!";
                    }
                    progressPercentage = (((i + 1) * 100) / targetCount);
                    worker.ReportProgress(progressPercentage);
                }
            }
        }

        private void subscriberWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pgbProgress.Value = (e.ProgressPercentage > 100) ? 100 : e.ProgressPercentage;
            lblCompleted.Text = e.ProgressPercentage + "%";
            dbSource.ResetBindings(false);
            dbSource.MoveNext();
        }

        private void subscriberWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            bool editStatus = false;
            string status = "";
            if (e.Cancelled == true)
            {
                MessageBox.Show("Proceso cancelado!", "Bulk Delete", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                editStatus = true;
                status = "Proceso cancelado!";
            }
            else if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, "Bulk Delete", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                editStatus = true;
                status = "Proceso cancelado por error!";
            }
            else
            {
                dbSource.ResetBindings(false);
                dbSource.MoveLast();
                MessageBox.Show("Proceso completado!", "Bulk Delete", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            if (editStatus)
            {
                foreach (targetSubscriber target in targetSubscribers)
                {
                    if (target.subscriberStatus == "Listo para eliminar!") target.subscriberStatus = status;
                }
            }
            dtgTargets.Enabled = true;
            cmdCancel.Enabled = false;
            cmdSaveLog.Enabled = true;
            termTime = DateTime.Now;
        }

        private void deviceWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            targetDevice target;
            int progressPercentage = 0;
            int targetCount = targetDevices.Count;
            BackgroundWorker worker = (BackgroundWorker)sender;
            dbSource.MoveFirst();
            for (int i = 0; i <= (targetCount - 1); i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    Thread.Sleep(2000);
                    target = targetDevices[i];
                    target.deviceStatus = "";
                    if (target.subscriberCode != null) rebindSubscriber(ref target);
                    // Filtro eliminacion dispositivos 
                    String[] filteredDevices = { "6589551", 
                                                     "7353921", 
                                                     "7345701",
                                                     "6591381",
                                                     "7329471",
                                                     "7324141",
                                                     "6367821",
                                                     "4881901",
                                                     "6853951",
                                                     "6860281",
                                                     "6665261", 
                                                     "6367861",
                                                     "7148471",
                                                     "6971331",
                                                     "6436961",
                                                     "6982761",
                                                     "4089381",
                                                     "6937241",
                                                     "5201671",
                                                     "6078801",
                                                     "5779181",
                                                     "6936961",
                                                     "4925961",
                                                     "3928251",
                                                     "6506211",
                                                     "6289061",
                                                     "6804371",
                                                     "6932921",
                                                     "6386401",
                                                     "6932701",
                                                     "6837141",
                                                     "6930371",
                                                     "4671141",
                                                     "3596251",
                                                     "5221341",
                                                     "5581211",
                                                     "6904401",
                                                     "4060301",
                                                     "5143721",
                                                     "6405071",
                                                     "3818561",
                                                     "6255271",
                                                     "6779011",
                                                     "5939721",
                                                     "3594881",
                                                     "5868681",
                                                     "5981811",
                                                     "5173121",
                                                     "5918181",
                                                     "4002941",
                                                     "5098621"};
                    if (Array.IndexOf(filteredDevices, target.deviceID) < 0)
                    {
                        // Eliminar dispositivo
                        if (deleteDevice(target.deviceID))
                        {
                            target.deviceStatus += "dispositivo eliminado!";
                        }
                        else
                        {
                            target.deviceStatus += "dispositivo no eliminado!";
                        }
                    }
                    else
                    {
                        target.deviceStatus += "dispositivo filtrado!";
                    }
                    progressPercentage = (((i + 1) * 100) / targetCount);
                    worker.ReportProgress(progressPercentage);
                }
            }
        }

        private void deviceWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pgbProgress.Value = (e.ProgressPercentage > 100) ? 100 : e.ProgressPercentage;
            lblCompleted.Text = e.ProgressPercentage + "%";
            dbSource.ResetBindings(false);
            dbSource.MoveNext();
        }

        private void deviceWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            bool editStatus = false;
            string status = "";
            if (e.Cancelled == true)
            {
                MessageBox.Show("Proceso cancelado!", "Bulk Delete", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                editStatus = true;
                status = "Proceso cancelado!";
            }
            else if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, "Bulk Delete", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                editStatus = true;
                status = "Proceso cancelado por error!";
            }
            else
            {
                MessageBox.Show("Proceso completado!", "Bulk Delete", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            if (editStatus)
            {
                foreach (targetDevice target in targetDevices)
                {
                    if (target.deviceStatus == "Listo para eliminar!") target.deviceStatus = status;
                }
            }
            dtgTargets.Enabled = true;
            cmdCancel.Enabled = false;
            cmdSaveLog.Enabled = true;
            termTime = DateTime.Now;
        }

        #endregion

        #region Private Global Methods

        private void formatGrid()
        {

            if (rbtSubscribers.Checked)
            {
                // Subscribers
                dtgTargets.Columns[0].Width = 100;
                dtgTargets.Columns[1].Width = 150;
                dtgTargets.Columns[2].Width = 300;
                dtgTargets.Columns[3].Width = 100;
                dtgTargets.Columns[4].Width = 600;
                /*
                dtgTargets.Columns[0].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[1].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[2].TextAlignment = ContentAlignment.MiddleLeft;
                dtgTargets.Columns[3].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[4].TextAlignment = ContentAlignment.MiddleLeft;
                */
                dtgTargets.Columns[0].HeaderText = "ID";
                dtgTargets.Columns[1].HeaderText = "Suscriptor";
                dtgTargets.Columns[2].HeaderText = "Nombre";
                dtgTargets.Columns[3].HeaderText = "Dispositivos";
                dtgTargets.Columns[4].HeaderText = "Estado";

            }
            else
            {
                // Devices
                dtgTargets.Columns[0].Width = 150;
                dtgTargets.Columns[1].Width = 150;
                dtgTargets.Columns[2].Width = 150;
                dtgTargets.Columns[3].Width = 150;
                dtgTargets.Columns[4].Width = 150;
                dtgTargets.Columns[5].Width = 150;
                dtgTargets.Columns[6].Width = 600;
                /*
                dtgTargets.Columns[0].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[1].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[2].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[3].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[4].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[5].TextAlignment = ContentAlignment.MiddleCenter;
                dtgTargets.Columns[6].TextAlignment = ContentAlignment.MiddleLeft;
                */
                dtgTargets.Columns[0].HeaderText = "ID";
                dtgTargets.Columns[1].HeaderText = "MAC";
                dtgTargets.Columns[2].HeaderText = "OUI";
                dtgTargets.Columns[3].HeaderText = "Suscriptor";
                dtgTargets.Columns[4].HeaderText = "Disposicion";
                dtgTargets.Columns[5].HeaderText = "Ultimo Informe (M/D/A)";
                dtgTargets.Columns[6].HeaderText = "Estado";

                dtgTargets.Columns[5].ValueType = typeof(DateTime);
                //dtgTargets.Columns[5].FormatString = "{0: M/d/yyyy}";

            }
        }

        private void lockGUI()
        {
            cmdLoad.Enabled = false;
            rbtDevices.Enabled = false;
            rcbOrphanOnly.Enabled = false;
            rcbLastInform.Enabled = false;
            rdtLastInform.Enabled = false;
            rbtSubscribers.Enabled = false;
            nudMaxRecords.Enabled = false;
            rcbFutureDeviceOnly.Enabled = false;
        }

        private void unlockGUI()
        {
            cmdLoad.Enabled = true;
            rbtDevices.Enabled = true;
            nudMaxRecords.Enabled = true;
            rbtSubscribers.Enabled = true;
            rcbOrphanOnly.Enabled = rbtDevices.Checked;
            rcbLastInform.Enabled = rbtDevices.Checked;
            rcbFutureDeviceOnly.Enabled = rbtDevices.Checked;
            rdtLastInform.Enabled = rcbLastInform.Checked && rcbLastInform.Enabled;
        }

        private void resetGUI()
        {
            pgbProgress.Text = "";
            pgbProgress.Value = 0;
            lblCount.Text = "Objetos cargados: 0";
            lblCompleted.Text = "0%";
        }

        private void resetDataObjects()
        {

            dtgTargets.DataSource = null;
            dbSource.DataSource = null;
            if (rbtDevices.Checked)
            {
                if (targetDevices != null) targetDevices = null;
            }
            else
            {
                if (targetSubscribers != null) targetSubscribers = null;
            }
            if (calqResults != null) calqResults = null;
        }

        private string ConvertSelectedDataToString(DataGridView grid)
        {
            StringBuilder strBuild = new StringBuilder();

            for (int row = 0; row < grid.SelectedRows.Count; row++)
            {
                for (int cell = 0; cell < grid.SelectedRows[row].Cells.Count; cell++)
                {
                    strBuild.Append(grid.SelectedRows[row].Cells[cell].Value.ToString());
                    strBuild.Append("\t");
                }
                strBuild.Append("\n");
            }
            return strBuild.ToString();
        }

        #endregion

        #region Private Device Methods

        private void loadDevices()
        {
            pgbProgress.Style = ProgressBarStyle.Marquee;
            pgbProgress.MarqueeAnimationSpeed = 15;
            var bgTask = Task.Factory.StartNew(() => searchDevices());
            bgTask.ContinueWith
                (
                    resultTask =>
                    {
                        if (calqResults != null)
                        {
                            targetDevices = new List<targetDevice>();

                            foreach (calqResult deviceFound in calqResults)
                            {
                                targetDevices.Add(new targetDevice(
                                                                    deviceFound.fields.deviceId,
                                                                    deviceFound.fields.serialNumber,
                                                                    deviceFound.fields.oui,
                                                                    deviceFound.fields.subscriberCode,
                                                                    deviceFound.fields.disposition,
                                                                    deviceFound.fields.lastInform));
                            }

                            dbSource.DataSource = targetDevices;
                            dtgTargets.DataSource = dbSource;
                            formatGrid();
                            lblCount.Text = "Objectos cargados: " + dbSource.Count.ToString();
                            cmdCancel.Enabled = true;
                            cmdDelete.Enabled = true;
                        }
                        else
                        {
                            MessageBox.Show("La busqueda no genero resultados!", "Cargar elementos", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            unlockGUI();
                        }
                        pgbProgress.Style = ProgressBarStyle.Continuous;
                        pgbProgress.MarqueeAnimationSpeed = 0;
                    }, TaskScheduler.FromCurrentSynchronizationContext()
            );
        }

        private void searchDevices()
        {
            string filter = "";

            if (rcbFutureDeviceOnly.Checked) filter = " with (disposition in (FUTURE_DEVICE)";
            if (rcbOrphanOnly.Checked) filter += (filter == "") ? " with (hasSubscriberAssociation: false" : " and hasSubscriberAssociation: false";
            if (rcbLastInform.Checked) filter += (filter == "") ? " with (lastInform: to " + String.Format("{0:M/d/yyyy}", rdtLastInform.Value.Date) + ")" : " and lastInform: to " + String.Format("{0:M/d/yyyy}", rdtLastInform.Value.Date) + ")"; else filter += (filter != "") ? ")" : ""; // Date Format MM/DD/YYYY

            string query = "subscription " + filter + " show subscriberCode as \"subscriberCode\"  serialNumber as \"serialNumber\" oui as \"oui\" deviceId as \"deviceId\" disposition as \"disposition\" lastInform as \"lastInform\" sort lastInform desc";

            calqResults = phWS.calq(query, (int)nudMaxRecords.Value);
        }

        private bool deleteDevice(string deviceId)
        {
            return phWS.deleteDevice(deviceId);
        }

        private void rebindSubscriber(ref targetDevice sourceDevice)
        {
            // Validar si se cuenta con la informacion requerida
            if (sourceDevice.deviceMAC != null & sourceDevice.deviceOUI != null & sourceDevice.subscriberCode != null)
            {
                // Obtener los dispositivos que tengan la misma MAC pero distinto OUI
                string query = "subscription with (serialNumber: " + sourceDevice.deviceMAC + " and oui: not " + sourceDevice.deviceOUI + ") show subscriberCode as \"subscriberCode\"  serialNumber as \"serialNumber\" oui as \"oui\" deviceId as \"deviceId\" disposition as \"disposition\" ";
                calqResult[] results = phWS.calq(query, (int)nudMaxRecords.Value);
                // Validar si se encontraron resultados
                if (results != null)
                {
                    Thread.Sleep(1000);
                    // Obtener el suscriptor que se debe reasociar
                    Subscriber targetSubscriber = phWS.getSubscriberByCode(sourceDevice.subscriberCode.Trim());
                    // Validar si el subscriptor existe
                    if (targetSubscriber != null)
                    {
                        // Se observaron casos en los que la consulta retorno mas de un resultado incluyendo el mismo MAC y OUI a pesar del filtro presente en la consulta CALQ
                        foreach (calqResult result in results)
                        {
                            // Validar si el resultado actual tiene la misma MAC pero distinto OUI
                            if (result.fields.serialNumber.Trim() == sourceDevice.deviceMAC & result.fields.oui.Trim() != sourceDevice.deviceOUI)
                            {
                                // Validar que el resultado actual no este ligado a una suscripcion 
                                if (result.fields.subscriberCode == null)
                                {
                                    Thread.Sleep(1000);
                                    // Crear una nueva suscripcion para el suscriptor
                                    Subscriber.subscription newSubscription = new Subscriber.subscription();
                                    // Alimentar la nueva suscripcion con los datos del nuevo dispositivo
                                    newSubscription.sn = result.fields.serialNumber.Trim();
                                    newSubscription.oui = result.fields.oui.Trim();
                                    newSubscription.deviceId = result.fields.deviceId.Trim();
                                    newSubscription.disposition = result.fields.disposition.Trim();
                                    // Agregar la suscripcion al suscriptor
                                    targetSubscriber.subscriptions.Add(newSubscription);
                                    Thread.Sleep(1000);
                                    // Guardar los cambios                                        
                                    if (phWS.putSubscriber(targetSubscriber))
                                    {
                                        sourceDevice.deviceStatus = "suscriptor asociado al dispositivo con id: " + result.fields.deviceId.Trim() + " y ";
                                    }
                                    else
                                    {
                                        sourceDevice.deviceStatus = "error al asociar suscriptor al dispositivo con id: " + result.fields.deviceId.Trim() + " y ";
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                Thread.Sleep(1000);
            }
        }

        #endregion

        #region Private Subscriber Methods

        private void loadSubscribers()
        {
            pgbProgress.Style = ProgressBarStyle.Marquee;
            pgbProgress.MarqueeAnimationSpeed = 15;
            var bgTask = Task.Factory.StartNew(() => searchSubscribers());
            bgTask.ContinueWith
                (
                    resultTask =>
                    {
                        if (calqResults != null)
                        {
                            targetSubscribers = new List<targetSubscriber>();

                            foreach (calqResult subscriberFound in calqResults)
                            {
                                targetSubscribers.Add(new targetSubscriber(
                                                                    subscriberFound.id,
                                                                    subscriberFound.fields.subscriberCode,
                                                                    subscriberFound.fields.subscriberName,
                                                                    subscriberFound.fields.deviceCount));
                            }

                            dbSource.DataSource = targetSubscribers;
                            dtgTargets.DataSource = dbSource;
                            formatGrid();
                            lblCount.Text = "Objectos cargados: " + dbSource.Count.ToString();
                            cmdCancel.Enabled = true;
                            cmdDelete.Enabled = true;
                        }
                        else
                        {
                            MessageBox.Show("La busqueda no genero resultados!", "Cargar elementos", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            unlockGUI();
                        }
                        pgbProgress.Style = ProgressBarStyle.Continuous;
                        pgbProgress.MarqueeAnimationSpeed = 0;
                    }, TaskScheduler.FromCurrentSynchronizationContext()
            );
        }

        protected void searchSubscribers()
        {
            string query = "subscriber with deviceCount: 0.0 show subscriberCode as \"subscriberCode\" fullName as \"subscriberName\" deviceCount as \"deviceCount\" ";
            calqResults = phWS.calq(query, (int)nudMaxRecords.Value);
        }

        protected bool deleteSubscriber(string subscriberId)
        {
            return phWS.deleteSubscriber(subscriberId);
        }

        #endregion
    }
}
